package com.matt.service.impl;

import com.google.common.collect.Lists;
import com.matt.domain.*;
import com.matt.domain.course.*;
import com.matt.domain.teaching.CourseAreaPublic;
import com.matt.domain.teaching.CourseOfficial;
import com.matt.foundation.constant.ChildrenCourseConstant;
import com.matt.foundation.constant.CourseConstant;
import com.matt.foundation.constant.CourseEarlyConstant;
import com.matt.commons.dto.sso.StaffDTO;
import com.matt.commons.exception.BusinessException;

import com.matt.foundation.model.ErrorCode;
import com.matt.foundation.query.ChildrenCourseQuery;
import com.matt.commons.page.PagerQuery;
import com.matt.foundation.utils.DateUtil;
import com.matt.foundation.utils.annotation.OptsTrace;
import com.matt.foundation.vo.*;
import com.matt.foundation.vo.course.*;
import com.matt.foundation.vo.evaluate.Web.WebCompletedCourseListVo;
import com.matt.repository.*;
import com.matt.repository.base.ChildChildrenCourseItemRepository;
import com.matt.repository.base.ChildrenExtendInfoCourseRepository;
import com.matt.repository.base.CourseChangeStaffRepository;
import com.matt.repository.base.CoursePlanItemRepository;
import com.matt.repository.course.*;
import com.matt.repository.teaching.CourseAreaPublicRepository;
import com.matt.repository.teaching.CourseOfficialRepository;
import com.matt.service.*;
import com.matt.service.remoteCall.SsoCallService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.*;
import java.util.stream.Collectors;

import static com.matt.foundation.model.ErrorCode.*;

/**
 * *******************************
 * Created by Ron.
 * form com.matt
 * on 2017/9/7
 * *******************************
 */
@Service
public class ChildrenCourseServiceImpl implements ChildrenCourseService {

    @Autowired
    private ChildrenCourseRepository childrenCourseRepository;

    @Autowired
    private ChildrenCourseItemRepository childrenCourseItemRepository;

    @Autowired
    private CoursePlanRepository coursePlanRepository;

    @Autowired
    private CoursePlanItemRepository coursePanItemRepository;

    @Autowired
    private ChildrenExtendInfoRepository childrenExtendInfoRepository;

    @Autowired
    private ChildrenExtendInfoCourseRepository childrenExtendInfoCourseRepository;

    @Autowired
    private TeachingAreaRepository teachingAreaRepository;

    @Autowired
    private ChildChildrenCourseItemRepository childChildrenCourseItemRepository;

    @Autowired
    private CourseAreaPublicRepository courseAreaPublicRepository;

    @Autowired
    private CourseOfficialRepository courseOfficialRepository;

    @Autowired
    private SsoCallService ssoCallService;

    @Autowired
    private ChildrenCourseChangeRecordRepository childrenCourseChangeRecordRepository;

    @Autowired
    private CourseChangeStaffRepository courseChangeStaffRepository;

    @Autowired
    private ChildrenRepository childrenRepository;

    @Autowired
    private CourseEarlyService courseService;

//    @Autowired
//    private CoursePlanExtensionRepository coursePlanExtensionRepository;

    @Autowired
    private TeacherService teacherService;

    @Override
    public Page<ChildrenCourseListVo> getChildrenCoursePageByCondition(ChildrenCourseQuery query) {
        List<Object[]> objects = childrenExtendInfoCourseRepository.findChildrenCoursePage(query);
        List<ChildrenCourseListVo> list = objects.stream().map(o -> ChildrenCourseListVo.of(o)).collect(Collectors.toList());
        Long count = childrenExtendInfoCourseRepository.countChildrenCourse(query);
        return new PageImpl<ChildrenCourseListVo>(list, PageRequest.of(query.getPageNum(), query.getPageSize()), count);
    }

//    @OptsTrace(value = "0501")


    @Override
    public List<ChildrenCourseItemVo> getItemByChildrenCourseId(String childrenCourseId) {
        List<Object[]> objects = coursePanItemRepository.findByChildrenCourseIdAndStatus(childrenCourseId);
        List<ChildrenCourseItemVo> itemVoList = objects.stream().map(o -> ChildrenCourseItemVo.of(o)).collect(Collectors.toList());
        return itemVoList;
    }


    @Transactional
    @Override
    public Map modifyPlanDetail(String areaId, String childrenId, String childrenCourseId) {
        String todayBegin = DateUtil.millisToDateTime(new Date().getTime(), "yyyy-MM-dd");
        List<WebCourseListVo> coursePlanList = courseService.getCourseListByArea(areaId, todayBegin);

        Children children = childrenRepository.getOne(childrenId);
        List<ChildrenCourseItemVo> doingList = getItemByChildrenCourseId(childrenCourseId);
        List<Object[]> completedCourseList = childChildrenCourseItemRepository.findCompletedCourseByChildrenId(childrenId);
        List<WebCourseItemListVo> courseList = Lists.newArrayList();
        coursePlanList.forEach(o -> {
            if (CourseConstant.CourseType.AREA_BUILD.codeOf() == o.getCourseType()) {
                CourseAreaPublic courseAreaPublic = courseAreaPublicRepository.getOne(o.getCourseEarlyId());
                courseList.add(WebCourseItemListVo.of(o, doingList, courseAreaPublic.getTypeName()));
            }
            if (CourseConstant.CourseType.PUBLIC.codeOf() == o.getCourseType()) {
                CourseOfficial courseOfficial = courseOfficialRepository.getOne(o.getCourseEarlyId());
                courseList.add(WebCourseItemListVo.of(o, doingList, courseOfficial.getTypeName()));
            }

            if (CourseConstant.CourseType.SAT.codeOf() == o.getCourseType()) {
                courseList.add(WebCourseItemListVo.of(o, doingList, null));
            }
        });
        List<WebCompletedCourseListVo> voList = Lists.newArrayList();
        completedCourseList.forEach(o -> {
            voList.add(WebCompletedCourseListVo.of(o));
        });
        Map response = new HashMap();
        response.put("allCoursePanList", courseList);
        response.put("children", children);
        response.put("completedCourseList", voList);
        return response;
    }


    @OptsTrace(code = "0502")
    @Override
    public Boolean modifyLeftCourseTime(String ticket, String childrenId, String remark, Integer times) {
        ChildrenExtendInfo childrenExtendInfo = childrenExtendInfoRepository.findByChildrenId(childrenId);
        childrenExtendInfo.setEarlyLeftCourseNum(childrenExtendInfo.getEarlyLeftCourseNum() == -1 ? times : childrenExtendInfo.getEarlyLeftCourseNum() + times);
        childrenExtendInfoRepository.save(childrenExtendInfo);
        StaffDTO staffDTO = ssoCallService.getStaffDTO(ticket);
        ChildrenCourseChangeRecord changeRecord = ChildrenCourseChangeRecord.of(staffDTO.getId(), childrenId, remark, times, childrenExtendInfo.getEarlyLeftCourseNum(), staffDTO.getRealName());
        childrenCourseChangeRecordRepository.save(changeRecord);
        return true;
    }

    @Override
    public Page<PadTeacherCoursePlanListVo> getHistoryCoursePlan(String teacherId, String areaId, PagerQuery query) {
        Date todayBegin = DateUtil.getCurrentDayBeginAndEnd(DateUtil.millisToDateTime(System.currentTimeMillis(), "yyyy-MM-dd")).get("beg");
        List<CoursePlan> coursePlans = coursePlanRepository.findByCourseDateAfterAndTeacherIdAndAreaId(todayBegin, teacherId, areaId, query.getPageNum()*query.getPageSize(), query.getPageSize());
        Long count = coursePlanRepository.countByCourseDateAfterAndTeacherIdAndAreaId(todayBegin, teacherId, areaId);

        List<CoursePlan> hasChildrenPlans = Lists.newArrayList();
        coursePlans.forEach(o -> {
            if (hasChildren(o.getId()))
                hasChildrenPlans.add(o);
        });
        List<PadTeacherCoursePlanListVo> teacherCoursePlanList = Lists.newArrayList();
        hasChildrenPlans.forEach(c -> {
//            TeachingArea area = teachingAreaRepository.getOne(c.getTeachingAreaId());
//            List<ChildrenCourseItemDO> itemList = childChildrenCourseItemRepository.findByChildrenByCoursePlanId(c.getId());
//            PadTeacherCoursePlanListVo vo = PadTeacherCoursePlanListVo.of(c, area, itemList);
//            teacherCoursePlanList.add(vo);
        });
        return new PageImpl<PadTeacherCoursePlanListVo>(teacherCoursePlanList, PageRequest.of(query.getPageNum(), query.getPageSize()), count);
    }



    @Override
    public WebCoursePlanDetailVo getWebCoursePlanDetail(StaffDTO staff, String planId) {
        CoursePlan coursePlan = coursePlanRepository.getOne(planId);

        TeachingArea area = teachingAreaRepository.getOne(coursePlan.getTeachingAreaId());

        return WebCoursePlanDetailVo.of(coursePlan, area, staff, /*extension,*/ null, null);
    }

    @Override
    public List<CourseEvaluateListVo> getCourseNonEvaluate(String teacherId) {
        List<Object[]> objects = childChildrenCourseItemRepository.findChildrenCourseNonEvaluateList(teacherId, ChildrenCourseConstant.ItemStatus.USED.codeOf());
        List<CourseEvaluateListVo> courseEvaluateListVos = objects.stream().map(o -> CourseEvaluateListVo.of(o)).collect(Collectors.toList());
        return courseEvaluateListVos;
    }

    @OptsTrace(code = "0540")
    @Override
    public Map checkIn(StaffDTO staff, String courseItemId, Integer status, String remark) {
        ChildrenCourseItem childrenCourseItem = childrenCourseItemRepository.getOne(courseItemId);
        if (Objects.isNull(childrenCourseItem))
            throw new BusinessException(ErrorCode.CHILDREN_COURSE_ITEM_STATUS_ERROR, "该宝宝的这门课程已被修改，请刷新后重试");
        if (childrenCourseItem.getStatus() != ChildrenCourseConstant.ItemStatus.NON_USED.codeOf())
            throw new BusinessException(ErrorCode.CHILDREN_COURSE_ITEM_STATUS_ERROR, "该宝宝这门课程已经进行过了，请勿重复处理");

        //减去课程剩余时间
        ChildrenExtendInfo childrenExtendInfo = childrenExtendInfoRepository.findByChildrenId(childrenCourseItem.getChildrenId());
        if (childrenExtendInfo.getEarlyLeftCourseNum() - 1 < 0) {
            throw new BusinessException(CHILDREN_HAS_NOT_COURSE_TIME, "宝宝没有课程剩余时间了");
        }

        ChildrenCourse childrenCourse = childrenCourseRepository.getOne(childrenCourseItem.getChildrenCourseId());

        childrenCourseItem.setStatus(ChildrenCourseConstant.ItemStatus.USED.get(status).codeOf());
        childrenCourseItem.setRemark(remark);
        childrenCourseItemRepository.save(childrenCourseItem);

        if (status == ChildrenCourseConstant.ItemStatus.USED.codeOf()) {
            //正常签到
            childrenCourse.setOverCourseSize(childrenCourse.getOverCourseSize() + 1);
            childrenCourse.setTotalCourseSize(childrenCourse.getTotalCourseSize() - 1);
            childrenExtendInfo.setEarlyLeftCourseNum(childrenExtendInfo.getEarlyLeftCourseNum() - 1);
            childrenExtendInfoRepository.save(childrenExtendInfo);

            ChildrenCourseChangeRecord changeRecord = ChildrenCourseChangeRecord.of(staff.getId(), childrenCourse.getChildrenId(), "正常消课", -1, childrenExtendInfo.getEarlyLeftCourseNum(), staff.getRealName());
            childrenCourseChangeRecordRepository.save(changeRecord);
        } else if (status == ChildrenCourseConstant.ItemStatus.SKIP.codeOf()) {
            //旷课
            childrenCourse.setSkipCourseSize(childrenCourse.getSkipCourseSize() + 1);
            childrenCourse.setTotalCourseSize(childrenCourse.getTotalCourseSize() - 1);
            childrenExtendInfo.setEarlyLeftCourseNum(childrenExtendInfo.getEarlyLeftCourseNum() - 1);
            childrenExtendInfoRepository.save(childrenExtendInfo);

            ChildrenCourseChangeRecord changeRecord = ChildrenCourseChangeRecord.of(staff.getId(), childrenCourse.getChildrenId(), "旷课", -1, childrenExtendInfo.getEarlyLeftCourseNum(), staff.getRealName());
            childrenCourseChangeRecordRepository.save(changeRecord);
        } else if (status == ChildrenCourseConstant.ItemStatus.LEAVE.codeOf()) {
            childrenCourse.setTotalCourseSize(childrenCourse.getTotalCourseSize() - 1);
            //请假
            childrenCourse.setLeaveCourseSize(childrenCourse.getLeaveCourseSize() + 1);
        }
        childrenCourseRepository.save(childrenCourse);

        Map response = new HashMap();
        response.put("status", ChildrenCourseConstant.ItemStatus.USED.get(status).codeOf());
        response.put("remark", remark);
        return response;
    }


    @Override
    public List<CourseChangeRecordVo> getRecordsByChildren(String childrenId) {
        List<Object[]> objects = courseChangeStaffRepository.findRecordsByChildren(childrenId);
        return objects.stream().map(o -> CourseChangeRecordVo.of(o)).collect(Collectors.toList());
    }


    @Override
    public CoursePlan beginCourse(StaffDTO staff, List<Map> childrenCourseStatusDtoList,  String[] teacherIds, String coursePlanId) {
        CoursePlan coursePlan = coursePlanRepository.getOne(coursePlanId);
        if (coursePlan.getCourseStatus() != CourseEarlyConstant.CourseStatus.STARTING.codeOf())
            throw new BusinessException(COURSE_PLAN_EARLY_PROCESSED,"早教课程已经处理");

        coursePlan.setCourseStatus(CourseEarlyConstant.CourseStatus.PROCESSED.codeOf());
        coursePlan.setBeginCourseTime(new Date());
        coursePlanRepository.save(coursePlan);

        for (Map m:childrenCourseStatusDtoList){
            checkIn(staff, m.get("childrenCourseItemId").toString(), Integer.valueOf(m.get("status").toString()), "");
        }

        //处理老师课程表历史记录
        teacherService.precessCourse(coursePlanId);
        return coursePlan;
    }

    @Override
    public boolean hasChildren(String planId) {
        List<ChildrenCourseItem> items = childrenCourseItemRepository.findByCoursePlanId(planId);
        if (Objects.nonNull(items) && items.size() > 0)
            return true;
        return false;
    }
}
